<template>
    <section class="flex gap-col-4">
        <div class="flex-1 flex flex-col gap-row-4">
            <div class="bg-white box-border pa-4">
                <DataQuery v-model:model="queryParameter" @query="query" @reset="reset" />
            </div>

            <div class="flex-1 bg-white box-border pa-4 flex flex-col">
                <div class="w-full pb-4 box-border flex items-center justify-between">
                    <div class="inline-flex items-center gap-col-2">
                        <n-button @click="insertData" type="primary">添加数据</n-button>
                        <n-button @click="batchDeleteData">批量删除</n-button>
                    </div>
                    <TableOperator @refresh="query" v-model:list="selectList" />
                </div>

                <NDataTable
                    class="flex-1 h-full"
                    :indent="20"
                    :data="treeData"
                    :loading="loading"
                    :columns="columnList"
                    :row-key="(row: Data) => row.identity"
                    :striped="true"
                    :bordered="true"
                    :flex-height="true"
                    :single-line="false"
                    default-expand-all
                    v-model:checked-row-keys="keyList">
                </NDataTable>
            </div>
        </div>

        <n-modal
            v-model:show="formVisible"
            :auto-focus="false"
            :close-on-esc="false"
            preset="card"
            :style="{width: '800px'}"
            :title="formTitle"
            size="large"
            :bordered="false"
            :segmented="{content: 'soft', footer: 'soft'}">
            <DataForm :identity="dataInfo.identity" @confirm="formConfirm" @cancel="formCancel" />
        </n-modal>
    </section>
</template>

<script setup lang="ts">
import {Api} from '@/api/type'
import DataForm from './form.vue'
import {h, ref, watch} from 'vue'
import DataQuery from './query.vue'
import {BaseApi} from '@/api/base-api'
import {useTable} from '@/hook/use-table'
import {TableColumn} from 'naive-ui/es/data-table/src/interface'
import TableOperator from '@/component/common/table-operator.vue'
import {NButton, NDataTable, NModal, NSpace, NTag, useDialog, useMessage} from 'naive-ui'
// -------------------------------------------------
type R<T> = Api.Common.R<T>;
type Data = Api.System.Route;
type PageRecord<T> = Api.Common.PageRecord<T>;
type PageParameter = Api.Common.PageParameter<Data>;
type Route = Data & {
    children?: Array<Route>;
}
// -------------------------------------------------
const dialog = useDialog()
const message = useMessage()
const baseApi = new BaseApi<Data>('route')
const formTitle = ref<string>('')
const formVisible = ref<boolean>(false)

const {
    data,
    loading,
    getData,
    keyList,
    columnList,
    selectList,
    queryParameter,
    resetParameter
} = useTable<Data, TableColumn<Data>>({
    queryFn: async (query: PageParameter): Promise<R<PageRecord<Data>>> => {
        query = {...query, page: 1, size: 99999}
        let result: R<PageRecord<Data>> = await baseApi.getPageInfo(query)
        if (result.code == 0) {
            return result
        } else {
            throw Error(result.message)
        }
    },
    queryParameter: {
        name: '',
        authority: '',
        path: '',
        component: '',
        type: '',
        visible: '',
        status: ''
    },
    pageParameter: {
        page: 1,
        size: 99999
    },
    columnList: () => [
        {
            type: 'selection',
            title: '选择列',
            align: 'center',
            titleAlign: 'center',
            width: 48
        },
        {
            title: '菜单名称',
            key: 'name',
            align: 'left',
            titleAlign: 'center'
        },
        {
            title: '权限标识',
            key: 'authority',
            align: 'center',
            titleAlign: 'center',
            render(row: Data) {
                if (row.type == 3) {
                    return h(NTag, {}, {default: () => row.authority})
                } else {
                    return ''
                }
            }
        },
        {
            title: '路由地址',
            key: 'path',
            align: 'center',
            titleAlign: 'center'
        },
        {
            title: '文件路径',
            key: 'component',
            align: 'center',
            titleAlign: 'center'
        },
        {
            title: '类型',
            key: 'type',
            align: 'center',
            titleAlign: 'center',
            render(row: Data) {
                if (row.type == 1) {
                    return h(NTag, {}, {default: () => '目录'})
                }
                if (row.type == 2) {
                    return h(NTag, {}, {default: () => '菜单'})
                }
                if (row.type == 3) {
                    return h(NTag, {}, {default: () => '权限'})
                }
                return ''
            }
        },
        {
            title: '排序',
            key: 'sort',
            align: 'center',
            titleAlign: 'center'
        },
        {
            title: '是否启用',
            key: 'status',
            align: 'center',
            titleAlign: 'center',
            render(row: Data) {
                if (row.type == 1) {
                    return h(NTag, {type: 'primary'}, {default: () => '启用'})
                } else {
                    return h(NTag, {type: 'error'}, {default: () => '禁用'})
                }
            }
        },
        {
            title: '操作',
            key: 'action',
            align: 'center',
            titleAlign: 'center',
            render(row: Data) {
                return h(NSpace, {'justify': 'space-around'}, {
                        default: () => [
                            h(NButton, {onClick: () => updateData(row), size: 'small', type: 'primary', strong: true, secondary: true}, {default: () => '修改'}),
                            h(NButton, {onClick: () => deleteData(row), size: 'small', type: 'error', strong: true, secondary: true}, {default: () => '删除'})
                        ]
                    }
                )
            }
        }
    ] as TableColumn<Data>[]
})

const treeData = ref<Array<Route>>([])
const dataInfo = ref<Partial<Data>>({})

watch(data, (value) => {
    treeData.value = generateTree(value)
})

async function reset() {
    resetParameter()
    await getData()
}

async function query() {
    await getData()
}

/**
 * 组装用户路由树
 */
const generateTree = (list: Array<Data>): Array<Route> => {
    list = JSON.parse(JSON.stringify(list))
    let _map: Map<string, Route> = list.reduce((map: Map<string, Route>, item: Data) => {
        map.set(item.identity, item)
        return map
    }, new Map<string, Route>())

    list.forEach((item: Data) => {
        let parent: Route | undefined = _map.get(item.parent)
        let current: Route | undefined = _map.get(item.identity)
        if (parent) {
            if (!parent?.children) {
                parent.children = []
            }
            if (current) {
                parent.children.push(current)
            }
            _map.set(item.parent, parent)
        }
    })
    return list.filter((item: Data): boolean => item.parent == '0')
}

/**
 * 添加数据
 */
async function insertData() {
    dataInfo.value = {}
    formTitle.value = '添加数据'
    formVisible.value = true
}

/**
 * 更新数据
 */
async function updateData(item: Data) {
    dataInfo.value = item
    formTitle.value = '修改数据'
    formVisible.value = true
}

/**
 * 删除数据
 */
async function deleteData(item: Data) {
    dialog.warning({
        title: '提示',
        content: '确定进行删除操作?',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: async () => {
            await baseApi.removeData(item.identity)
            await getData()
        }
    })
}

/**
 * 批量删除数据
 */
async function batchDeleteData() {
    if (keyList.value.length == 0) {
        message.error('请先选择要删除的数据后再试')
        return false
    }
    dialog.warning({
        title: '提示',
        content: '确定进行删除操作?',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: async () => {
            await baseApi.batchRemoveData(keyList.value)
            await getData()
        }
    })
}

async function formConfirm() {
    formVisible.value = false
    await getData()
}

async function formCancel() {
    formVisible.value = false
    await getData()
}
</script>
